package com.zmm.book.keep.service.impl;

import com.zmm.book.keep.dao.BillDao;
import com.zmm.book.keep.dao.MonthBillDao;
import com.zmm.book.keep.dao.MonthBillDetailDao;
import com.zmm.book.keep.model.MonthBill;
import com.zmm.book.keep.model.MonthBillDetail;
import com.zmm.book.keep.service.MonthBillService;
import com.zmm.book.keep.vo.ConsumeVo;
import com.zmm.book.keep.vo.MonthBillVo;
import com.zmm.common.base.model.Query;
import com.zmm.common.enums.KindEnum;
import com.zmm.common.enums.SourceEnums;
import com.zmm.util.time.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 900045
 * @description:
 * @name MonthBillServiceImpl
 * @date By 2021-10-28 11:51:12
 */
@Slf4j
@Service
public class MonthBillServiceImpl implements MonthBillService {
	
	@Resource
	private BillDao billDao;
	
	@Resource
	private MonthBillDetailDao monthBillDetailDao;
	
	@Resource
	private MonthBillDao monthBillDao;
	


	@Override
	public List<MonthBillDetail> jobSearchMonthBillByDate(String date) {

		Long startTime = DateUtil.getNowTime();

		List<MonthBillDetail> monthBillDetailList = new ArrayList<>();
		// 信用卡还款 type 24
		MonthBillDetail repayment = billDao.collectBillByDateAndType(date, KindEnum.REPAYMENT.code,1);
		if (!ObjectUtils.isEmpty(repayment)) {
			addMonthBillDetail(monthBillDetailList,date,KindEnum.REPAYMENT.code,KindEnum.REPAYMENT.name,repayment);
		}

		// 股票投入 type 30
		MonthBillDetail stock = billDao.collectBillByDateAndType(date, KindEnum.STOCK.code,1);
		if (!ObjectUtils.isEmpty(stock)){
			addMonthBillDetail(monthBillDetailList,date,KindEnum.STOCK.code,KindEnum.STOCK.name,stock);
		}

		// 基金投入 type 31
		MonthBillDetail fund = billDao.collectBillByDateAndType(date, KindEnum.FUND.code,1);
		if (!ObjectUtils.isEmpty(fund)){
			addMonthBillDetail(monthBillDetailList,date,KindEnum.FUND.code,KindEnum.FUND.name,fund);
		}
		
		// 房贷 type 26
		MonthBillDetail houseLoan = billDao.collectBillByDateAndType(date, KindEnum.HOUSE_LOAN.code,1);
		if (!ObjectUtils.isEmpty(houseLoan)) {
			addMonthBillDetail(monthBillDetailList,date,KindEnum.HOUSE_LOAN.code,KindEnum.HOUSE_LOAN.name,houseLoan);
		}
		
		// 保险投资 type 17
		MonthBillDetail insuranceInvestment = billDao.collectBillByDateAndType(date, KindEnum.INSURANCE_INVESTMENT.code,1);
		if (!ObjectUtils.isEmpty(insuranceInvestment)) {
			addMonthBillDetail(monthBillDetailList,date,KindEnum.INSURANCE_INVESTMENT.code,KindEnum.INSURANCE_INVESTMENT.name,insuranceInvestment);
		}

		// 保险收益 type 27
		MonthBillDetail insuranceProfit = billDao.collectBillByDateAndType(date, KindEnum.INSURANCE_PROFIT.code,2);
		if (!ObjectUtils.isEmpty(insuranceProfit)) {
			addMonthBillDetail(monthBillDetailList,date,KindEnum.INSURANCE_PROFIT.code,KindEnum.INSURANCE_PROFIT.name,insuranceProfit);
		}

		// 股票卖出 type 32
		MonthBillDetail saleStock = billDao.collectBillByDateAndType(date, KindEnum.SALE_STOCK.code,2);
		if (!ObjectUtils.isEmpty(insuranceProfit)) {
			addMonthBillDetail(monthBillDetailList,date,KindEnum.SALE_STOCK.code,KindEnum.SALE_STOCK.name,saleStock);
		}

		// 基金卖出 type 33
		MonthBillDetail saleFund = billDao.collectBillByDateAndType(date, KindEnum.SALE_FUND.code,2);
		if (!ObjectUtils.isEmpty(insuranceProfit)) {
			addMonthBillDetail(monthBillDetailList,date,KindEnum.SALE_FUND.code,KindEnum.SALE_FUND.name,saleFund);
		}

		// 信用卡消费 type 29
		MonthBillDetail creditCardConsume = billDao.collectBillByDateAndForm(date, "信用卡",1);
		if (!ObjectUtils.isEmpty(creditCardConsume)){
			addMonthBillDetail(monthBillDetailList,date,KindEnum.CREDIT_CARD_CONSUME.code,KindEnum.CREDIT_CARD_CONSUME.name,creditCardConsume);
		}
		

		// 消费
		MonthBillDetail consume = billDao.collectBillByDateAndForm(date, "花呗",1);
		if (!ObjectUtils.isEmpty(consume)) {
			addMonthBillDetail(monthBillDetailList,date,KindEnum.CONSUME.code,KindEnum.CONSUME.name,consume);
		}
		
		// ==> 370 毫秒
		log.info("查询时长:{}",DateUtil.getNowTime() - startTime);

		batchSaveMonthBillDetail(date,1,monthBillDetailList);
		
		return monthBillDetailList;
	}
	
	/**
	 * 向 list 中添加 MonthBillDetail
	 * @author: 900045
	 * @date: 2021-10-28 17:42:18
	 * @throws 
	 * @param monthBillDetailList: 
	 * @param date: 
	 * @param kind: 
	 * @param explain: 
	 * @param monthBillDetail: 
	 * @return: void
	 **/
	private void addMonthBillDetail(List<MonthBillDetail> monthBillDetailList,String date,Integer kind,
									String explain,MonthBillDetail monthBillDetail){
		monthBillDetail.setForm(kind);
		monthBillDetail.setDescribe(explain);
		monthBillDetailList.add(monthBillDetail);
	}

	@Override
	public List<MonthBillDetail> jobSearchMonthBillByDate2(String date) {
		Long startTime = DateUtil.getNowTime();

		List<MonthBillDetail> monthBillDetailList = new ArrayList<>();
		// mode = 1
		searchExpend(monthBillDetailList,date);
		// mode = 2
		searchIncome(monthBillDetailList,date);
		
		// 消费
		List<ConsumeVo> consumeVoList = billDao.collectConsumeBillListByDate(date, 1);
		if (!CollectionUtils.isEmpty(consumeVoList)){
			consumeVoList.stream().forEach(consumeVo -> {
				if (KindEnum.CONSUME.name.equals(consumeVo.getForm())) {
					MonthBillDetail consume = new MonthBillDetail();
					consume.setTotalMoney(consumeVo.getTotalMoney());
					consume.setForm(KindEnum.CONSUME.code);
					addMonthBillDetail(monthBillDetailList,date,KindEnum.CONSUME.code,KindEnum.CONSUME.name,consume);
				} else {
					MonthBillDetail creditCardConsume = new MonthBillDetail();
					creditCardConsume.setTotalMoney(consumeVo.getTotalMoney());
					creditCardConsume.setForm(KindEnum.CREDIT_CARD_CONSUME.code);
					addMonthBillDetail(monthBillDetailList,date,KindEnum.CREDIT_CARD_CONSUME.code,KindEnum.CREDIT_CARD_CONSUME.name,creditCardConsume);
				}
			});
		}
		// ==>169 毫秒
		log.info("查询时长:{}",DateUtil.getNowTime() - startTime);
		
		return monthBillDetailList;
	}
	
	/**
	 * 支出的明细
	 * @author: 900045
	 * @date: 2021-10-28 20:06:55
	 * @throws 
	 * @param monthBillDetailList: 
	 * @param date: 
	 * @return: void
	 **/
	private void searchExpend(List<MonthBillDetail> monthBillDetailList, String date){
		List<Integer> typeList =new ArrayList<>();
		typeList.add(17);
		typeList.add(26);
		typeList.add(28);
		typeList.add(30);
		typeList.add(31);
		List<MonthBillDetail> monthBillDetails = billDao.collectIncomeBillListByDate(date, typeList, 1);
		traversalList(monthBillDetailList,date,monthBillDetails);
	}

	/**
	 * 收入的明细
	 * @author: 900045
	 * @date: 2021-10-28 20:07:03
	 * @throws 
	 * @param monthBillDetailList: 
	 * @param date: 
	 * @return: void
	 **/
	private void searchIncome(List<MonthBillDetail> monthBillDetailList, String date){
		List<Integer> typeList2 =new ArrayList<>();
		typeList2.add(27);
		typeList2.add(32);
		typeList2.add(33);

		List<MonthBillDetail> monthBillDetails = billDao.collectIncomeBillListByDate(date, typeList2, 2);
		traversalList(monthBillDetailList,date,monthBillDetails);
	}
	
	/**
	 * 遍历 封装 集合
	 * @author: 900045
	 * @date: 2021-10-28 20:17:18
	 * @throws 
	 * @param monthBillDetailList: 
	 * @param date: 
	 * @param monthBillDetails: 
	 * @return: void
	 **/
	private void traversalList(List<MonthBillDetail> monthBillDetailList,String date,List<MonthBillDetail> monthBillDetails){
		if (!CollectionUtils.isEmpty(monthBillDetails)) {
			monthBillDetails.stream().forEach(monthBillDetail -> {
				Integer kind = monthBillDetail.getForm();
				addMonthBillDetail(monthBillDetailList, date, kind, KindEnum.getKindEnum(kind), monthBillDetail);
			});
		}
	}


	@Override
	public List<MonthBillDetail> jobSearchMonthBillByDate3(String date) {
		Long startTime = DateUtil.getNowTime();
		List<MonthBillDetail> monthBillDetailList = billDao.collectMonthBillDetail(date);

		Map<Integer, List<MonthBillDetail>> listMap = monthBillDetailList.stream().collect(Collectors.groupingBy(MonthBillDetail::getCustomerId));
		if (!CollectionUtils.isEmpty(listMap)) {
			Iterator<Integer> iterator = listMap.keySet().iterator();
			while (iterator.hasNext()) {
				Integer customerId = iterator.next();
				List<MonthBillDetail> monthBillDetailListByCustomerId = listMap.get(customerId);
				batchSaveMonthBillDetail(date,customerId,monthBillDetailListByCustomerId);
			}
		}
		// ==> 查询时长:333
		log.info("查询时长:{}",DateUtil.getNowTime() - startTime);
		
		return monthBillDetailList;
	}

	@Override
	public void queryMonthBillList(Query<MonthBillVo> queryMonthBill) {
		Integer total = monthBillDao.countMonthBillList(queryMonthBill);
		if (total > 0) {
			queryMonthBill.setTotal(total);
			List<MonthBillVo> searchMonthBillList = monthBillDao.searchMonthBillList(queryMonthBill);
			queryMonthBill.setResults(searchMonthBillList);
		}
	}

	/**
	 * 批量保存月账单记录
	 * @author: 900045
	 * @date: 2021-10-29 14:04:14
	 * @throws 
	 * @param date:
	 * @param customerId:   
	 * @param monthBillDetailList: 
	 * @return: void
	 **/
	private void batchSaveMonthBillDetail(String date,Integer customerId,List<MonthBillDetail> monthBillDetailList) {
		if (!CollectionUtils.isEmpty(monthBillDetailList)) {
			MonthBill monthBill = new MonthBill();
			monthBillDetailList.stream().forEach(monthBillDetail -> {
				// 计算贷款 金额
				if (SourceEnums.l.code.equals(monthBillDetail.getForm())){
					BigDecimal loan = monthBill.getLoan() == null? BigDecimal.ZERO:monthBill.getLoan();
					monthBill.setLoan(loan.add(monthBillDetail.getTotalMoney()));
				}
				if (SourceEnums.m.code.equals(monthBillDetail.getForm())) {
					BigDecimal loan = monthBill.getLoan() == null? BigDecimal.ZERO:monthBill.getLoan();
					monthBill.setLoan(loan.add(monthBillDetail.getTotalMoney()));
				}
				if (SourceEnums.n.code.equals(monthBillDetail.getForm())) {
					BigDecimal loan = monthBill.getLoan() == null? BigDecimal.ZERO:monthBill.getLoan();
					monthBill.setLoan(loan.add(monthBillDetail.getTotalMoney()));
				}
				// 计算收入 金额
				if (SourceEnums.x.code.equals(monthBillDetail.getForm())) {
					monthBill.setIncome(monthBillDetail.getTotalMoney());
				}
				// 计算基金收益 金额
				if (SourceEnums.t.code.equals(monthBillDetail.getForm())) {
					// type = 20
					BigDecimal fundYield = monthBill.getFundYield() == null? BigDecimal.ZERO:monthBill.getFundYield();
					monthBill.setFundYield(fundYield.add(monthBillDetail.getTotalMoney()));
				}
				if (SourceEnums.s.code.equals(monthBillDetail.getForm())) {
					// type = 19
					BigDecimal fundYield = monthBill.getFundYield() == null? BigDecimal.ZERO:monthBill.getFundYield();
					monthBill.setFundYield(fundYield.subtract(monthBillDetail.getTotalMoney()));
				}
				// 计算股票收益 金额
				if (SourceEnums.u.code.equals(monthBillDetail.getForm())) {
					BigDecimal stockYield = monthBill.getStockYield() == null? BigDecimal.ZERO:monthBill.getStockYield();
					monthBill.setStockYield(stockYield.subtract(monthBillDetail.getTotalMoney()));
				}
				if (SourceEnums.v.code.equals(monthBillDetail.getForm())) {
					BigDecimal stockYield = monthBill.getStockYield() == null? BigDecimal.ZERO:monthBill.getStockYield();
					monthBill.setStockYield(stockYield.add(monthBillDetail.getTotalMoney()));
				}
				// 余额收益 金额
				if (SourceEnums.r.code.equals(monthBillDetail.getForm())) {
					BigDecimal balanceYield = monthBill.getBalanceYield() == null? BigDecimal.ZERO:monthBill.getBalanceYield();
					monthBill.setBalanceYield(balanceYield.add(monthBillDetail.getTotalMoney()));
				}
			});
			
			// 计算消费 金额
			BigDecimal lifeConsume = billDao.totalMoneyMonthBill(date, customerId,
												addType(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 0, 29));
			monthBill.setLifeConsume(lifeConsume);
			monthBill.setCustomerId(customerId);
			// 计算保险 金额
			BigDecimal insurance = billDao.totalMoneyMonthBill(date, customerId,addType(17));
			monthBill.setInsurance(insurance);
			monthBill.setMonth(date);

			// 消费占比
			monthBill.setConsumePoint(monthBill.getLifeConsume().divide(monthBill.getIncome(), 2,RoundingMode.HALF_UP));
			// 保险占比
			if (ObjectUtils.isEmpty(insurance)) {
				monthBill.setInsurancePoint(new BigDecimal(0));
			} else {
				monthBill.setInsurancePoint(monthBill.getInsurance().divide(monthBill.getIncome(), 2, RoundingMode.HALF_UP));
			}
			// 贷款占比

			monthBill.setLoanPoint(monthBill.getLoan().divide(monthBill.getIncome(), 2,RoundingMode.HALF_UP));
			monthBillDao.insertMonthBill(monthBill);
			
			monthBillDetailList.stream().forEach(monthBillDetail -> {
				monthBillDetail.setTaskId(monthBill.getTaskId());
			});
			Integer integer = monthBillDetailDao.insertBatch(monthBillDetailList);
			log.info("批量保存的数据量:{}", integer);
		}
	}
	
	/**
	 * 统计 bill 账单中的金额
	 * @author: 900045
	 * @date: 2021-10-29 15:32:23
	 * @throws 
	 * @param type: 
	 * @return: java.util.List<java.lang.Integer>
	 **/
	private List<Integer> addType(Integer... type){
		List<Integer> typeList =new ArrayList<>();
		if (!ObjectUtils.isEmpty(type)) {
			for (int i = 0; i <  type.length; i++) {
				typeList.add(type[i]);
			}
		}
		return typeList;
	}
}
